package xian.woniuxy.interceptor;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import xian.woniuxy.annotation.RequirePermissions;
import xian.woniuxy.domain.ResultVo;
import xian.woniuxy.entity.Permission;
import xian.woniuxy.entity.User;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author gao
 * @date 2023/07/05 16:22:57
 */
@Component
public class AuthInterceptor implements HandlerInterceptor {
    private static Logger logger = LoggerFactory.getLogger(AuthInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 如果是预检请求，则直接放行
        String method = request.getMethod();
        if ("OPTIONS".equals(method)) {
            return true;
        }
        // 如果用户已经登录，则放行，没有登录则不放行
        HttpSession session = request.getSession();
        User loginUser = (User) session.getAttribute("loginUser");

        if (loginUser == null) {
            return false;
        }

        // 获取用户已有权限
        List<Permission> userPermissions = loginUser.getPermissions();
        List<String> stringPermissions = userPermissions.stream().map(p -> p.getPermissionName()).collect(Collectors.toList());
        logger.debug("用户已有权限：" + stringPermissions);

        // 获取用户要访问的资源所需的权限
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        RequirePermissions requirePermissions = handlerMethod.getMethodAnnotation(RequirePermissions.class);
        if (requirePermissions == null) {
            return true;
        }

        String permission = requirePermissions.value();
        logger.debug("资源所需权限：" + permission);

        // 如果用户已有权限完全包含资源所需权限则放行，否则不放行
        boolean contains = stringPermissions.contains(permission);
        if (!contains) {
            response.setContentType("application/json;charset=utf-8");
            ResultVo resultVo = ResultVo.failure("无权限");
            ObjectMapper objectMapper = new ObjectMapper();
            String json = objectMapper.writeValueAsString(resultVo);
            response.getWriter().println(json);
            logger.debug("无权限访问资源，不放行");
            return false;
        }
        logger.debug("有权限访问资源，放行");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    }
}
